package com.summerbird.mallchat.common.chat.dao;


import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.summerbird.mallchat.common.chat.domain.entity.GroupMember;
import com.summerbird.mallchat.common.chat.domain.enums.GroupRoleEnum;
import com.summerbird.mallchat.common.chat.mapper.GroupMemberMapper;
import com.summerbird.mallchat.common.chat.service.cache.GroupMemberCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery;
import static com.summerbird.mallchat.common.chat.domain.enums.GroupRoleEnum.ADMIN_LIST;

/**
 * <p>
 * 群成员表 服务实现类
 * </p>
 *
 * @author <a href="https://github.com/zongzibinbin">abin</a>
 * @since 2023-07-16
 */
@Service
public class GroupMemberDao extends ServiceImpl<GroupMemberMapper, GroupMember> {

    @Autowired
    private GroupMemberCache groupMemberCache;

    public GroupMember getMember(Long groupId, Long uid) {
        return lambdaQuery()
                .eq(GroupMember::getUid, uid)
                .eq(GroupMember::getGroupId, groupId)
                .one();
    }

    public List<Long> getMemberUidList(Long groupId) {
        List<GroupMember> list = lambdaQuery().eq(GroupMember::getGroupId, groupId).select(GroupMember::getUid).list();
        return list.stream().map(GroupMember::getUid).collect(Collectors.toList());
    }

    public Map<Long, Integer> getMemberMapRole(Long roomGroupId, List<Long> uidList) {
        List<GroupMember> groupMemberList = lambdaQuery()
                .eq(GroupMember::getGroupId, roomGroupId)
                .in(GroupMember::getUid, uidList)
                .select(GroupMember::getUid, GroupMember::getRole)
                .in(GroupMember::getRole, ADMIN_LIST)
                .list();
        return groupMemberList.stream().collect(Collectors.toMap(GroupMember::getUid, GroupMember::getRole));
    }

    public boolean isLord(Long groupId, Long uid) {
        GroupMember member = lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .eq(GroupMember::getUid, uid)
                .eq(GroupMember::getRole, GroupRoleEnum.LEADER.getType())
                .one();
        return ObjectUtil.isNotNull(member);
    }

    public boolean isManager(Long groupId, Long uid) {
        GroupMember member = lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .eq(GroupMember::getUid, uid)
                .eq(GroupMember::getRole, GroupRoleEnum.MANAGER.getType())
                .one();
        return ObjectUtil.isNotNull(member);
    }

    public List<Long> getMemberUidBatch(Long groupId, List<Long> uidList) {
        List<GroupMember> groupMemberList = lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .in(GroupMember::getUid, uidList)
                .select(GroupMember::getUid)
                .list();
        return groupMemberList.stream().map(GroupMember::getUid).collect(Collectors.toList());
    }

    public Map<Long, GroupMember> getMemberBatch(Long groupId, List<Long> uidList) {
        List<GroupMember> groupMemberList = lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .in(GroupMember::getUid, uidList)
                .select(GroupMember::getUid)
                .list();
        return groupMemberList.stream().collect(Collectors.toMap(GroupMember::getUid, Function.identity()));
    }

    public GroupMember getSelfGroup(Long uid) {
        return lambdaQuery()
                .eq(GroupMember::getUid, uid)
                .eq(GroupMember::getRole, GroupRoleEnum.LEADER.getType())
                .one();
    }

    public List<Long> getManagerMembers(Long groupId) {
        return lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .eq(GroupMember::getRole, GroupRoleEnum.MANAGER.getType())
                .list()
                .stream()
                .map(GroupMember::getUid)
                .collect(Collectors.toList());
    }

    /**
     * 判断群成员是否在群组中
     * @param roomId
     * @param uidList
     * @return
     */
    public Boolean isGroupShip(Long roomId, List<Long> uidList) {
        List<Long> memberUidList = groupMemberCache.getMemberUidList(roomId);
        return memberUidList.containsAll(uidList);
    }

    public void addAdmin(Long groupId, List<Long> uidList) {
        lambdaUpdate()
            .eq(GroupMember::getGroupId, groupId)
            .in(GroupMember::getUid, uidList)
            .set(GroupMember::getRole, GroupRoleEnum.MANAGER.getType())
            .update();
    }

    public void removeAdmin(Long groupId, List<Long> uidList) {
        lambdaUpdate()
            .eq(GroupMember::getGroupId, groupId)
            .in(GroupMember::getUid, uidList)
            .set(GroupMember::getRole, GroupRoleEnum.MEMBER.getType())
            .update();
    }

    public void removeByGroupId(Long groupId, List<Long> uidList) {
        LambdaUpdateWrapper<GroupMember> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(GroupMember::getUid, uidList);
        wrapper.eq(GroupMember::getGroupId, groupId);
        this.remove(wrapper);
    }

    public List<Long> getmemberBatch(Long groupId, List<Long> uidList) {
        return lambdaQuery()
                .eq(GroupMember::getGroupId, groupId)
                .in(GroupMember::getUid, uidList)
                .select(GroupMember::getUid)
                .list()
                .stream()
                .map(GroupMember::getUid)
                .collect(Collectors.toList());
    }
}
